﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using SDK;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ThermoGroupSample
{
    public partial class FormInfrared : Form
    {
        private const float EM = 1.00f; // emissivity

        private MagDevice mDevice;
        private int mFPAWidth;
        private int mFPAHeight;
        private int mVideoWidth;
        private int mVideoHeight;
        private bool mIsDDTLoaded;

        private Timer mMgsPopTimer;

        // temperature measuring
        private int mMousePosX;
        private int mMousePosY;
        private Rectangle mTempRect; // client axis

        // Option
        private bool mIsMouseTempEnabled;
        private bool mIsRectTempEnabled;
        private GroupSDK.STREAM_TYPE mStreamType;

        // Ui drawing objects
        Pen mPen;
        Font mFont;
        Brush mBrush;

        // Delegate
        private GroupSDK.DelegateNewFrame mNewFrameDelegate;
        private GroupSDK.DelegateReconnect mReconnDelegate;
        private GroupSDK.DelegateObjReco mObjRecoDelegate;
        private GroupSDK.DelegateIrregularROIReport mRoiReportDelegate;

        // Object detect related
        public object mRecoLock; // locker by object detector
        public uint mRecObjNum;
        public const uint MAX_OBJ_NUM = 20;
        public GroupSDK.OBJ_INFO[] mObjInfo;

        #region 二次开发

        private double avgTemp;//ROI平均温度
        private Point startPoint; // 记录绘制矩形的起始点
        private Point endPoint;   // 记录绘制矩形的结束点
        private bool isDrawing;   // 标志是否正在绘制矩形
        public Rectangle nTempRect; // 矩形画完
        public bool isRoi = true;//是否启用ROI
        private int[] avgTemps = new int[8];//ROI平均温度集合
        private int[] maxTemps = new int[8];//ROI最大温度集合
        //private List<Point> listNgCount = new List<Point>();
        public List<Rectangle> rectangles = new List<Rectangle>();
        private Dictionary<Point, bool> dicResult = new Dictionary<Point, bool>();//检测结果
        #endregion
        public FormInfrared()
        {
            InitializeComponent();

            mObjInfo = new GroupSDK.OBJ_INFO[MAX_OBJ_NUM];
            mRecoLock = new object();

            mPen = new Pen(Brushes.LightGreen, 2);
            mFont = new Font("宋体", 10, FontStyle.Bold);
            mBrush = new SolidBrush(Color.LightGreen);

            this.DoubleBuffered = true; // 开启双缓冲，减少闪烁
        }

        public void bindDevice(MagDevice device)
        {
            mDevice = device;
        }

        public void enableMouseTemp(bool enabled)
        {
            mMousePosX = -1;
            mMousePosY = -1;
            mIsMouseTempEnabled = enabled;
            Invalidate(false);
        }

        public void enableRectTemp(bool enabled)
        {
            mIsRectTempEnabled = enabled;
            //mTempRect = new Rectangle(Width / 4, Height / 4, Width / 2, Height / 2);
            mTempRect = new Rectangle(254, 130, 130, 130);
            Invalidate(false);
        }

        // Play live camera
        public bool play(string ip, GroupSDK.STREAM_TYPE streamType)
        {
            if (mDevice == null)
            {
                return false;
            }

            mStreamType = streamType;

            if (mIsDDTLoaded)
            {
                mDevice.DisLinkCamera();
                mIsDDTLoaded = false;
            }

            // link camera
            if (!mDevice.LinkCamera(ip, 3000))
            {
                return false;
            }

            mNewFrameDelegate = new GroupSDK.DelegateNewFrame(newFrameCome);
            mReconnDelegate = new GroupSDK.DelegateReconnect(reconnectEventCome);
            mObjRecoDelegate = new GroupSDK.DelegateObjReco(objRecoCome);
            mRoiReportDelegate = new GroupSDK.DelegateIrregularROIReport(roiReportCome);

            GroupSDK.CAMERA_INFO camInfo = mDevice.GetCamInfo();

            mFPAWidth = camInfo.intFPAWidth;
            mFPAHeight = camInfo.intFPAHeight;
            mVideoWidth = camInfo.intVideoWidth;
            mVideoHeight = camInfo.intVideoHeight;

            // play camera
            if (!mDevice.StartProcessImage(mNewFrameDelegate, streamType, IntPtr.Zero))
            {
                mDevice.DisLinkCamera();
                return false;
            }

            setUsualPara();

            if (!mDevice.SetReConnectCallBack(mReconnDelegate, IntPtr.Zero))
            {
                // Set reconnect callback fail
            }

            // set detect callback
            if (!mDevice.SetObjRecoCallBack(mObjRecoDelegate, IntPtr.Zero))
            {
                // Set object detect or recognize callback fail
            }

            if (!mDevice.SetIrregularROIReportExCallBack(mRoiReportDelegate, IntPtr.Zero))
            {
                // Set roi report callback fail
            }

            mIsDDTLoaded = false;
            return true;
        }

        private void setUsualPara()
        {
            // set color palette
            mDevice.SetColorPalette(GroupSDK.COLOR_PALETTE.IRONBOW);

            // get fix para
            GroupSDK.FIX_PARAM para = new GroupSDK.FIX_PARAM();
            var option = mDevice.GetFixPara(ref para);

            // modify and set fix para, usually not modified
            // para.fEmissivity = EM;
            // para.fTaoFilter = 1.0f;
            mDevice.SetFixPara(para, option);
        }

        // stop live/ddt/mgs
        public void stop()
        {
            if (mMgsPopTimer != null)
            {
                mMgsPopTimer.Stop();
            }

            if (mDevice != null)
            {
                if (mDevice.IsProcessingImage())
                {
                    mDevice.StopProcessImage();
                }

                if (mDevice.VisIsPlaying())
                {
                    mDevice.VisStop();
                }

                if (mDevice.IsLinked())
                {
                    mDevice.DisLinkCamera();
                }
            }

            mIsDDTLoaded = false;
            Invalidate(false);
        }

        // save bitmap
        public bool saveBMP()
        {
            if (mDevice == null)
            {
                return false;
            }

            if (!mDevice.SaveBMP(1, "mag_ir.bmp") || !mDevice.SaveBMP(2, "mag_ir_bar.bmp"))
            {
                return false;
            }

            return true;
        }

        // save temperature to file
        public bool saveDDT()
        {
            if (mDevice == null)
            {
                return false;
            }

            return mDevice.SaveDDT("mag_ir.ddt");
        }

        // will be called when a new infrared frame received from camera
        private void newFrameCome(uint channel, int intCamTemp, int intFFCCounter, int intCamState, int intStreamType, IntPtr userData)
        {
            Invalidate(false);
        }

        private void reconnectEventCome(uint channelIndex, uint recentHeartBeatTick, int state, IntPtr userData)
        {
            Console.WriteLine("Reconnect happen, state=" + state);
        }
        // draw all needed
        private void FormInfrared_Paint(object sender, PaintEventArgs e)
        {
            if (mDevice == null || (!mDevice.IsProcessingImage() && !mIsDDTLoaded))
            {
                return;
            }

            Bitmap infraredBmp = null;
            Bitmap colorbarBmp = null;
            int mouseTemp = 0, rectMaxTemp = 0;
            Point maxClientPt = new Point();

            // get ir data with lock(only lock() can ensure that all data got in the same frame)
            mDevice.Lock();

            mouseTemp = getMouseTemp();
            rectMaxTemp = getRectTemp(ref maxClientPt);

            infraredBmp = mDevice.GetOutputVideoBitmapData();
            if (infraredBmp == null)
            {
                infraredBmp = mDevice.GetOutputBitmapData();
            }
            // colorbarBmp = mDevice.GetOutputColorbarBitmapData();

            mDevice.Unlock();

            Graphics graphic = e.Graphics;

            // draw ir
            if (infraredBmp != null)
            {
                graphic.DrawImage(infraredBmp, new Rectangle(0, 0, Width, Height), 0, 0,
                    infraredBmp.Width, infraredBmp.Height, GraphicsUnit.Pixel);
            }

            // draw colorbar
            if (colorbarBmp != null)
            {
                graphic.DrawImage(colorbarBmp,
                    new Rectangle(Width - colorbarBmp.Width - 8, (Height - colorbarBmp.Height) / 2, colorbarBmp.Width, colorbarBmp.Height),
                    0, 0, colorbarBmp.Width, colorbarBmp.Height, GraphicsUnit.Pixel);
            }

            // draw rect temp
            if (mIsRectTempEnabled)
            {
                // draw shape
                graphic.DrawRectangle(mPen, mTempRect);
                graphic.DrawLine(mPen, maxClientPt.X - 4, maxClientPt.Y, maxClientPt.X + 4, maxClientPt.Y);
                graphic.DrawLine(mPen, maxClientPt.X, maxClientPt.Y - 4, maxClientPt.X, maxClientPt.Y + 4);

                // draw text
                string text = (rectMaxTemp * 0.001f).ToString("0.0");
                graphic.DrawString(text, mFont, mBrush, maxClientPt.X + 2, maxClientPt.Y + 5);
            }

            // draw mouse temp
            if (mIsMouseTempEnabled && mMousePosX > 0 && mMousePosY > 0)
            {
                // draw text
                string text = (mouseTemp * 0.001f).ToString("0.0");
                graphic.DrawString(text, mFont, mBrush, mMousePosX + 10, mMousePosY);
            }

            // draw objects
            drawDetectObjs(graphic, Width, Height);

            //正在画矩形
            if (isDrawing && endPoint.X != -1 && isRoi)
            {
                // 创建一个Graphics对象，用于绘制
                Graphics g = e.Graphics;

                // 创建一个画笔，指定颜色和宽度
                //Pen pen = new Pen(Color.Blue, 2);
                // 计算矩形的位置和大小
                int x = Math.Min(startPoint.X, endPoint.X);
                int y = Math.Min(startPoint.Y, endPoint.Y);
                int width = Math.Abs(startPoint.X - endPoint.X);
                int height = Math.Abs(startPoint.Y - endPoint.Y);

                // 使用画笔绘制矩形
                g.DrawRectangle(mPen, x, y, width, height);
                nTempRect = new Rectangle(x, y, width, height);
                // 释放资源
                //pen.Dispose();
            }
            if (!isDrawing && endPoint.X != -1 && isRoi)
            {
                // 创建一个Graphics对象，用于绘制
                Graphics g = e.Graphics;
                g.DrawRectangle(mPen, nTempRect);
            }

            //页面加载8个区域矩形
            for (int i = 0; i < 8; i++)
            {
                string section = "point" + i.ToString();
                int startX = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "startX", FormMain.path));
                int startY = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "startY", FormMain.path));
                int endX = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "endX", FormMain.path));
                int endY = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "endY", FormMain.path));
                //if (startX == 0 && startY == 0 && endX == 0 && endY == 0)
                //{
                //    continue;
                //}
                //else
                //{

                //}
                Rectangle rectangle = new Rectangle(startX, startY, endX - startX, endY - startY);
                Point maxRpoClientPt = new Point();
                var roiTemps = getNewRectTemp(startX, startY, endX, endY, ref maxRpoClientPt);
                graphic.DrawRectangle(mPen, rectangle);
                // ROI最大温度显示
                string text = (roiTemps.Item1 * 0.001f).ToString("0.0");
                graphic.DrawString(text, mFont, mBrush, maxRpoClientPt.X + 2, maxRpoClientPt.Y + 5);
                //ROI平均温度存储
                avgTemps[i] = roiTemps.Item2;
                //ROI最大温度存储
                maxTemps[i] = roiTemps.Item1;
                graphic.DrawString($"area_{i + 1}", new Font("宋体", 15, FontStyle.Bold), new SolidBrush(Color.BlueViolet), startX, startY - 23);
                rectangles.Add(rectangle);
            }
            //信息标注
            //for (int i = 0; i < listNgCount.Count; i++)
            //{
            //    graphic.DrawString("NG", new Font("宋体", 30, FontStyle.Bold), new SolidBrush(Color.Red), listNgCount[i].X + 2, listNgCount[i].Y + 5);
            //}
            if (dicResult.Count > 0)
            {
                foreach (var item in dicResult)
                {
                    if (item.Value)
                    {
                        graphic.DrawString("OK", new Font("宋体", 30, FontStyle.Bold), new SolidBrush(Color.LightGreen), item.Key.X + 2, item.Key.Y + 5);
                    }
                    else
                    {
                        graphic.DrawString("NG", new Font("宋体", 30, FontStyle.Bold), new SolidBrush(Color.Red), item.Key.X + 2, item.Key.Y + 5);
                    }
                }
            }
        }

        private int getMouseTemp()
        {
            if (mDevice == null || mMousePosX < 0 || mMousePosY < 0)
            {
                return int.MaxValue;
            }

            // client -> fpa
            Point fpaPt = Util.axesTransfer(mMousePosX, mMousePosY, Width, Height, mFPAWidth, mFPAHeight);

            int temp = 0;
            if (mStreamType == GroupSDK.STREAM_TYPE.STREAM_VIDEO)
            {
                // it will request a temperature from a remote camera, not real-time
                int[] info = new int[5];
                if (!mDevice.GetRectTemperatureInfo((uint)fpaPt.X, (uint)fpaPt.Y, (uint)fpaPt.X, (uint)fpaPt.Y, info))
                {
                    return int.MaxValue;
                }
                temp = info[1];
            }
            else
            {
                // it will get a temperature from local received data, real-time
                temp = mDevice.GetTemperatureProbe((uint)fpaPt.X, (uint)fpaPt.Y, 1);
                if (temp == -0x7FFFFFFF)
                {
                    return int.MaxValue;
                }
            }

            // fix temperature
            GroupSDK.FIX_PARAM para = new GroupSDK.FIX_PARAM();
            if (mDevice.GetFixPara(ref para) != GroupSDK.FixSelection.FixSelectionDisabled)
            {
                temp = mDevice.FixTemperature(temp, para.fEmissivity, (uint)fpaPt.X, (uint)fpaPt.Y);
            }
            return temp;
        }

        private int getRectTemp(ref Point maxClientPt)
        {
            if (mDevice == null)
            {
                return int.MaxValue;
            }

            // client -> fpa
            Point fpaPt0 = Util.axesTransfer(mTempRect.Left, mTempRect.Bottom, Width, Height, mFPAWidth, mFPAHeight);
            Point fpaPt1 = Util.axesTransfer(mTempRect.Right, mTempRect.Top, Width, Height, mFPAWidth, mFPAHeight);

            int[] info = new int[5];
            if (!mDevice.GetRectTemperatureInfo((uint)fpaPt0.X, (uint)fpaPt0.Y, (uint)fpaPt1.X, (uint)fpaPt1.Y, info))
            {
                return int.MaxValue;
            }

            // fpa -> client
            uint fpaX = 0, fpaY = 0;
            mDevice.ConvertPos2XY((uint)info[4], ref fpaX, ref fpaY);
            maxClientPt = Util.axesTransfer((int)fpaX, (int)fpaY, mFPAWidth, mFPAHeight, Width, Height);

            // fix temperature
            GroupSDK.FIX_PARAM para = new GroupSDK.FIX_PARAM();
            int maxTemp = info[1];
            if (mDevice.GetFixPara(ref para) != GroupSDK.FixSelection.FixSelectionDisabled)
            {
                maxTemp = mDevice.FixTemperature(maxTemp, para.fEmissivity, fpaX, fpaY);
            }
            avgTemp = info[2];
            return maxTemp;
        }

        public void FormInfrared_MouseMove(object sender, MouseEventArgs e)
        {
            mMousePosX = e.X;
            mMousePosY = e.Y;
            Invalidate(false);

            if (isDrawing)
            {
                endPoint = e.Location;
                this.Invalidate(); // 引发窗体重绘
            }
            if (nTempRect.X!=0 && nTempRect.Y!=0 && nTempRect.Width!=0 && nTempRect.Height!=0)
            {
                FormMain.Instance.textBoxStartX.Text = nTempRect.X.ToString();
                FormMain.Instance.textBoxEndX.Text = (nTempRect.X + nTempRect.Width).ToString();
                FormMain.Instance.textBoxStartY.Text = nTempRect.Y.ToString();
                FormMain.Instance.textBoxEndY.Text = (nTempRect.Y + nTempRect.Height).ToString();
            }
           
        }

        private void FormInfrared_MouseLeave(object sender, EventArgs e)
        {
            mMousePosX = -1;
            mMousePosY = -1;
            Invalidate(false);
        }

        // Load offline temperature file
        public bool loadDDT(string fileName)
        {
            if (mDevice == null)
            {
                return false;
            }

            mStreamType = GroupSDK.STREAM_TYPE.STREAM_TEMPERATURE;
            mIsDDTLoaded = mDevice.LoadDDT(fileName);
            if (mIsDDTLoaded)
            {
                GroupSDK.CAMERA_INFO camInfo = mDevice.GetCamInfo();
                mFPAWidth = camInfo.intFPAWidth;
                mFPAHeight = camInfo.intFPAHeight;
                mVideoWidth = camInfo.intVideoWidth;
                mVideoHeight = camInfo.intVideoHeight;
            }

            Invalidate(false);
            return mIsDDTLoaded;
        }

        public bool isPlaying()
        {
            return mIsDDTLoaded || (mDevice == null ? false : mDevice.IsProcessingImage());
        }

        // save offline temperature stream start
        public bool startMgsRecording()
        {
            if (mDevice == null)
            {
                return false;
            }

            return mDevice.LocalStorageMgsRecord("mag_ir.mgs", 1);
        }

        // save offline temperature stream stop
        public void stopMgsRecording()
        {
            if (mDevice == null)
            {
                return;
            }

            mDevice.LocalStorageMgsStop();
        }

        public bool isMgsRecording()
        {
            if (mDevice == null)
            {
                return false;
            }

            return mDevice.IsLocalMgsRecording();
        }

        // Load offline temperature stream file
        public bool loadMGS(string fileName)
        {
            if (mDevice == null)
            {
                return false;
            }

            mStreamType = GroupSDK.STREAM_TYPE.STREAM_TEMPERATURE;
            mNewFrameDelegate = new GroupSDK.DelegateNewFrame(newFrameCome);

            if (mDevice.LocalStorageMgsPlay(fileName, mNewFrameDelegate, IntPtr.Zero) <= 0)
            {
                return false;
            }

            GroupSDK.CAMERA_INFO camInfo = mDevice.GetCamInfo();
            mFPAWidth = camInfo.intFPAWidth;
            mFPAHeight = camInfo.intFPAHeight;
            mVideoWidth = camInfo.intVideoWidth;
            mVideoHeight = camInfo.intVideoHeight;

            setUsualPara();

            if (mMgsPopTimer == null)
            {
                mMgsPopTimer = new Timer();
                mMgsPopTimer.Interval = 40;
                mMgsPopTimer.Tick += new EventHandler(mgsPopTimer);
            }
            mMgsPopTimer.Start();

            return true;
        }

        public bool uploadRoiToCamera()
        {
            if (mDevice == null || !mDevice.IsLinked())
            {
                return false;
            }

            GroupSDK.IRREGULAR_ROI[] rois;

            if (!mIsRectTempEnabled)
            {
                rois = new GroupSDK.IRREGULAR_ROI[0];
            }
            else
            {
                Point pt0 = Util.axesTransfer(mTempRect.Left, mTempRect.Bottom, Width, Height, mFPAWidth, mFPAHeight);
                Point pt1 = Util.axesTransfer(mTempRect.Right, mTempRect.Top, Width, Height, mFPAWidth, mFPAHeight);

                rois = new GroupSDK.IRREGULAR_ROI[1];

                rois[0].sROIName = Util.getUTF8Bytes("Rect");
                rois[0].intROIType = 2;
                rois[0].intEmissivity = 100;
                rois[0].intAlarmTemp = 100000;
                rois[0].intTextPos = 0;
                rois[0].intSamplePeriod = 5;

                rois[0].x0 = pt0.X;
                rois[0].y0 = pt0.Y;
                rois[0].x1 = pt1.X;
                rois[0].y1 = pt1.Y;

                rois[0].Points = new GroupSDK.POINT[7];
                rois[0].intPtNumber = 2;
                rois[0].Points[0].x = pt0.X;
                rois[0].Points[0].y = pt0.Y;
                rois[0].Points[1].x = pt1.X;
                rois[0].Points[1].y = pt1.Y;

                rois[0].dwReserved = 0;
                rois[0].bNovolatile = 1;
            }

            return mDevice.SetIrregularROIs(rois, (uint)rois.Length);
        }

        //////////////// mgs pop ///////////////////////////////////////
        private void mgsPopTimer(object sender, EventArgs e)
        {
            if (mDevice != null && !mDevice.LocalStorageMgsPopFrame())
            {
                mDevice.LocalStorageMgsStop();
                mMgsPopTimer.Stop();
            }
            Invalidate(false);
        }

        //////////////// roi report related /////////////////////////////
        private void roiReportCome(uint channelIndex, GroupSDK.IRREGULAR_ROI_REPORT[] reports, uint num, IntPtr userData)
        {
            foreach (GroupSDK.IRREGULAR_ROI_REPORT report in reports)
            {
                string name = Encoding.UTF8.GetString(report.baseinfo.sROIName);
                name = name.Substring(0, name.IndexOf('\0'));
                string temp = (report.baseinfo.intMaxTemp * 0.001f).ToString("0.0");
                //Console.WriteLine(name + ": " + temp);
            }
        }

        //////////////// object detect related //////////////////////////

        private void objRecoCome(uint channel, GroupSDK.OBJ_INFO[] reports, uint objNum, IntPtr userData)
        {
            if (objNum > MAX_OBJ_NUM)
            {
                objNum = MAX_OBJ_NUM;
            }

            lock (mRecoLock)
            {
                Array.Copy(reports, mObjInfo, objNum);
                mRecObjNum = objNum;
            }
        }

        private void drawDetectObjs(Graphics graphic, int w, int h)
        {
            lock (mRecoLock)
            {
                for (uint i = 0; i < mRecObjNum; i++)
                {
                    GroupSDK.OBJ_INFO roi = mObjInfo[i];

                    // get object region on screen
                    Point pt0 = Util.axesTransfer(roi.rectIr.left, roi.rectIr.top, mFPAWidth, mFPAHeight, w, h);
                    Point pt1 = Util.axesTransfer(roi.rectIr.right, roi.rectIr.bottom, mFPAWidth, mFPAHeight, w, h);

                    int x0 = pt0.X, y0 = pt1.Y, x1 = pt1.X, y1 = pt0.Y;

                    // draw object region
                    graphic.DrawRectangle(mPen, x0, y0, x1 - x0, y1 - y0);

                    // get max temp position on screen
                    int fpaY = roi.shortSamplePointIrY;
                    int fpaX = roi.shortSamplePointIrX;
                    int x = Util.axesTransfer(fpaX, fpaY, mFPAWidth, mFPAHeight, w, h).X;
                    int y = Util.axesTransfer(fpaX, fpaY, mFPAWidth, mFPAHeight, w, h).Y;//默认右上

                    // draw cursor
                    int halfLen = 4;
                    Point pt = Util.axesTransfer(fpaX, fpaY, mFPAWidth, mFPAHeight, w, h);
                    graphic.DrawLine(mPen, pt.X - halfLen, pt.Y, pt.X + halfLen, pt.Y);
                    graphic.DrawLine(mPen, pt.X, pt.Y - halfLen, pt.X, pt.Y + halfLen);

                    // draw temp
                    int intTemp = roi.intBodyTemp;
                    string sText = (intTemp * 0.001f).ToString("0.0");
                    graphic.DrawString(sText, mFont, mBrush, x0, y0 - 15);
                }
            }
        }

        #region 扩展二次开发

        /// <summary>
        /// ROI温度分析
        /// </summary>
        /// <returns></returns>
        public async Task<bool[]> GetRectPoinTemp()
        {
            //listNgCount.Clear();
            dicResult.Clear();
            int allNg = 0;//定义NG总数
            bool[] results = new bool[8];//测试结果
            //double[] resTemp = new double[8];//温度信息
            return await Task.Run(() =>
            {
                for (int i = 0; i < 8; i++)
                {
                    string section = "point" + i.ToString();
                    int startX = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "startX", FormMain.path));
                    int startY = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "startY", FormMain.path));
                    int endX = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "endX", FormMain.path));
                    int endY = Convert.ToInt32(FormMain.Instance.extension.INIRead(section, "endY", FormMain.path));
                    int setCount = Convert.ToInt32((endX - startX) * (endY - startY) * FormMain.Instance.setNgPercent);
                    if (startX == 0 && startY == 0 && endX == 0 && endY == 0)
                    {
                        continue;
                    }
                    else
                    {
                        Dictionary<double, int> frequencyMap = new Dictionary<double, int>();
                        List<double> temps = new List<double>();
                        int currentNg = 0;
                        double tempAvg = Math.Round((avgTemps[i] * 0.001f), 1);
                        double tempMax = Math.Round((maxTemps[i] * 0.001f), 1);
                        if (tempMax > FormMain.Instance.setTempRage)
                        {//检测是否A/B面装反：通过判断测试最大温度值是否超过冷面温度上限设定值
                            //listNgCount.Add(new Point(startX, startY));
                            dicResult.Add(new Point(startX, startY), false);
                            allNg++;
                            continue;
                        }
                        for (int k = 0; k < endX - startX; k++)
                        {
                            for (int j = 0; j < endY - startY; j++)
                            {
                                Point fpaPt = Util.axesTransfer(startX + k, startY + j, Width, Height, mFPAWidth, mFPAHeight);
                                int temp = mDevice.GetTemperatureProbe((uint)fpaPt.X, (uint)fpaPt.Y, 1);
                                GroupSDK.FIX_PARAM para = new GroupSDK.FIX_PARAM();
                                if (mDevice.GetFixPara(ref para) != GroupSDK.FixSelection.FixSelectionDisabled)
                                {
                                    temp = mDevice.FixTemperature(temp, para.fEmissivity, (uint)fpaPt.X, (uint)fpaPt.Y);
                                }
                                double tempRes = Math.Round((temp * 0.001f), 1);
                                if (Math.Abs(tempRes - tempAvg) > FormMain.Instance.setTemp)
                                {
                                    currentNg++;
                                }
                                temps.Add(tempRes);
                            }
                        }
                        if (currentNg > setCount)
                        {
                            allNg++;
                            //listNgCount.Add(new Point(startX, startY));
                            dicResult.Add(new Point(startX, startY), false);
                            results[i] = false;
                        }
                        else
                        {
                            results[i] = true;
                            dicResult.Add(new Point(startX, startY), true);
                        }

                        //tsst
                        foreach (double item in temps)
                        {
                            if (frequencyMap.ContainsKey(item))
                            {
                                frequencyMap[item]++;
                            }
                            else
                            {
                                frequencyMap[item] = 1;
                            }
                        }
                    }
                }
                this.Invalidate();
                return results;
            });
        }
        public async Task<List<int>> GetRectPoinTemp2()
        {
            int setCount = Convert.ToInt32(16900 * 0.02);
            List<int> listCount = new List<int>();
            return await Task.Run(() =>
            {
                for (int k = 0; k < 200000; k++)
                {
                    int currentNg = 0;
                    double tempAvg = Math.Round((avgTemp * 0.001f), 1);
                    List<double> temps = new List<double>();
                    for (int i = 0; i < 130; i++)
                    {
                        for (int j = 0; j < 130; j++)
                        {
                            Point fpaPt = Util.axesTransfer(254 + i, 130 + j, Width, Height, mFPAWidth, mFPAHeight);
                            double temp = Math.Round((mDevice.GetTemperatureProbe((uint)fpaPt.X, (uint)fpaPt.Y, 1) * 0.001f), 1);
                            if (Math.Abs(temp - tempAvg) > 0.5)
                            {
                                currentNg++;
                            }
                            temps.Add(temp);
                        }
                    }
                    listCount.Add(currentNg);
                }
                return listCount;
            });
        }

        public void FormInfrared_MouseClick(object sender, MouseEventArgs e)
        {
            int iX = e.X;
            int iY = e.Y;
        }

        public void FormInfrared_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startPoint = e.Location;
                endPoint = new Point(-1, -1);
                isDrawing = true;
            }
        }

        public void FormInfrared_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isDrawing = false;
                endPoint = e.Location;
                // this.Invalidate(); // 完成绘制后引发一次重绘以显示最终矩形
            }
        }

        private Tuple<int, int> getNewRectTemp(int startX, int startY, int endX, int endY, ref Point maxRpoClientPt)
        {
            if (mDevice == null)
            {
                return Tuple.Create(int.MaxValue, int.MaxValue);
            }

            // client -> fpa
            Point fpaPt0 = Util.axesTransfer(startX, endY, Width, Height, mFPAWidth, mFPAHeight);
            Point fpaPt1 = Util.axesTransfer(endX, startY, Width, Height, mFPAWidth, mFPAHeight);

            int[] info = new int[5];
            if (!mDevice.GetRectTemperatureInfo((uint)fpaPt0.X, (uint)fpaPt0.Y, (uint)fpaPt1.X, (uint)fpaPt1.Y, info))
            {
                return Tuple.Create(int.MaxValue, int.MaxValue);
            }

            // fpa -> client
            uint fpaX = 0, fpaY = 0;
            mDevice.ConvertPos2XY((uint)info[4], ref fpaX, ref fpaY);
            maxRpoClientPt = Util.axesTransfer((int)fpaX, (int)fpaY, mFPAWidth, mFPAHeight, Width, Height);

            // fix temperature
            GroupSDK.FIX_PARAM para = new GroupSDK.FIX_PARAM();
            int maxTemp = info[1];
            if (mDevice.GetFixPara(ref para) != GroupSDK.FixSelection.FixSelectionDisabled)
            {
                maxTemp = mDevice.FixTemperature(maxTemp, para.fEmissivity, fpaX, fpaY);
            }

            int avgTemp = info[2];
            if (mDevice.GetFixPara(ref para) != GroupSDK.FixSelection.FixSelectionDisabled)
            {
                avgTemp = mDevice.FixTemperature(avgTemp, para.fEmissivity, fpaX, fpaY);
            }
            return Tuple.Create(maxTemp, avgTemp);
        }
        #endregion
    }
}
